home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / ALLSWAGS.ZIP / SWAGN-R.ZIP / NETWORK.SWG / 0032_IPX Communication Protocol Primitives.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-09-04  |  27.3 KB  |  764 lines

  1. {
  2. From: greg.miller@shivasys.com
  3.  
  4. >Could you tell me where to get the ipx units?
  5.  
  6. I'll post the IPX source here again.  (Perhaps this should go into
  7. the FAQ? :)  There seems to be a big demand for this unit.
  8.  
  9. { ipx - IPX communication protocol primitives.          }
  10. unit ipx;
  11.  
  12. interface uses DOS;
  13.  
  14. type
  15.      MessageStr          = String;
  16.      IPX_REGS            = Registers;
  17.      Byte4               = array[0..3] of byte;
  18.      NetworkNumber       = Byte4;
  19.      NetworkNode         = array[0..5] of byte;
  20.  
  21.      ECB                 = record
  22.                             link_address          : Pointer;
  23.                             event_service_routine : Pointer;
  24.                             in_use                : byte;
  25.                             completion_code       : byte;
  26.                             socket_number         : word;
  27.                             ipx_workspace         : Byte4;
  28.                             driver_workspace      : array[0..11] of 
  29. byte;
  30.                             immediate_address     : NetworkNode;
  31.                             fragment_count          : word;
  32.                             fragment                : array [0..1] of 
  33. record
  34.                                                           address : 
  35. pointer;
  36.                                                           length  : 
  37. word;
  38.                                                     end;
  39.                            end;
  40.  
  41.      IPXHEADER           = record
  42.                             checksum              : word;
  43.                             length                : word;
  44.                             transport_control     : byte;
  45.                             packet_type           : byte;
  46.                             dest_network_number   : NetworkNumber;
  47.                             dest_network_node     : NetworkNode;
  48.                             dest_network_socket   : word;
  49.                             source_network_number : NetworkNumber;
  50.                             source_network_node   : NetworkNode;
  51.                             source_network_socket : word;
  52.                            end;
  53.  
  54. { ZeroEcb - store zeros in all ecb fields.
  55.  Pre: e is an ECB.
  56.         Post: e is fully zeroed. }
  57. procedure ZeroEcb( var e : ECB );
  58.  
  59. { ZeroHeader - Store zeros in all header fields.
  60.  Pre: h is an IPXHEADER.
  61.         Post: h is fulled zeroed. }
  62. procedure ZeroHeader( var h : IPXHEADER );
  63.  
  64. { Get1stConnectionNumber - Return first connection number for user name
  65.  Pre: username is valid Novell user name
  66.         Post: Returns first connection number username is logged on or
  67.          0 if not logged on. }
  68. function Get1stConnectionNumber( username : string ) : word;
  69.  
  70. { GetInternetAddress - Get the network:node address for a connection.
  71.  Pre: connection_number is valid for a logged on user.
  72.         Post: network_number is valid number of network.
  73.          physical_node is valid station node.             
  74.  }
  75. function GetInternetAddress(    connection_number : byte;
  76.                             var network_number : NetworkNumber; {hi:lo}
  77.                             var physical_node : NetworkNode ) : integer;
  78.  
  79. { IPXSPXNotLoaded - Executed when ipxspx called but not loaded.
  80.  Pre: IPX not loaded.
  81.         Post: Execution aborted. }
  82. procedure IPXSPXNotLoaded(var NovRegs : Registers);
  83.  
  84. { IPXInstalled - Determine if IPX is installed on workstation.
  85.  Pre: Either IPX is or is not installed.
  86.         Post:   If IPX installed initialize global IPXLocation to IPX 
  87. entry
  88.          point and return TRUE.
  89.                 Otherwise initialize global IPXLocation to 
  90. IPXSPXNotLoaded
  91.                 entry point and return FALSE.  }
  92. function IPXInstalled : Boolean;
  93.  
  94. { IPXSPX - Call ipxspx at address in IPXLocation.
  95.  Pre: IPXInstalled has been called.
  96.          IPX is installed and NovRegs assigned IPX or SPX function
  97.          and parameter values. Not checking is done.
  98.         Post:  IPX or SPX function is called.
  99.          NovRegs assigned by call. }
  100. procedure IPXSPX(var NovRegs:Registers);
  101.  
  102. { IPXRelinquishControl - Give ipx momentary control of CPU.
  103.  Pre: IPX loaded.
  104.         Post: IPX execution done. }
  105. procedure IPXRelinquishControl;
  106.  
  107. { IPXCancelEvent - Cancels pending event associated with ECB.
  108.             Pre:  e is valid ECB.
  109.                    Post: 00 - Success.
  110.                      F9 - ECB cannot be canceled.
  111.                          FF - ECB not in use. }
  112. function IPXCancelEvent( var e : ECB ) : byte;
  113.  
  114. { IPXDisconnectFromTarget - Notify listening node that communications 
  115. woth
  116.        specified socket are being terminated.
  117.  Pre: number:node:socket are valid.
  118.         Post: Node notified.   }
  119. procedure IPXDisconnectFromTarget( network_number : NetWorkNumber;
  120.                                    network_node   : NetWorkNode;
  121.                                    network_socket : word );
  122.  
  123. { IPXScheduleEvent - Schedule processing of ECB after timer ticks.
  124.  Pre: ticks is number of 18.2 per second ticks.
  125.                 e is a valid ECB at the time processing occurs.
  126.         Post: e is processed after timer ticks. }
  127. procedure IPXScheduleEvent( ticks : word; var e : ECB );
  128.  
  129. { IPXOpenSocket - Open an application socket.
  130.  Pre: socket to use (BBA-7FFF). All assumed short-lived.
  131.         Post: 00 - Success.
  132.          FE - Socket table full.
  133.                 FF - Socket already open.  }
  134. function IPXOpenSocket( socket : word ) : byte;
  135.  
  136. { IPXCloseSocket - Close socket. No harm if already closed.
  137.  Pre: socket to close.
  138.         Post: socket is closed. }
  139. procedure IPXCloseSocket( socket : word );
  140.  
  141. { IPXListenForPacket - Submit an ECB for use when packet received. Must
  142.                        have ECB available when packet received by IPX.
  143.  Pre: e storage is available when ECB processed by IPX.
  144.          e.socket_number opened.
  145.                 e.event_svc-routine valid routine or NULL.
  146.                 e.fragment_count normally 2.
  147.                 e.fragment[0].address to IPX Header buffer.
  148.                 e.fragment[0].length = 30.
  149.                 e.fragment[1].address to data area <=546 bytes long.
  150.                 e.fragment[1].length = length of data area.
  151.         Post: If socket opened, e is added to pool and return TRUE.
  152.          Otherwise return FALSE.    }
  153. function IPXListenForPacket( var e : ECB ) : Boolean;
  154.  
  155. { IPXSendPacket - Send packet using given ECB.
  156.  Pre: e storage is available when ECB processed by IPX.
  157.          e.socket_number opened.
  158.                 e.event_svc-routine valid routine or NULL.
  159.                 e.immediate_address is address of destination 
  160. workstation.
  161.                 e.fragment_count normally 2.
  162.                 e.fragment[0].address to IPX Header buffer.
  163.                 e.fragment[0].length = 30.
  164.                 e.fragment[1].address to data area <=546 bytes long.
  165.                 e.fragment[1].length = length of data area.
  166.         Post: e.completion_code of: 00 - Message sent.
  167.             FC - Event canceled.
  168.                                         FD - Bad packet.   }
  169.  
  170. { IPXGetLocalTarget - Get the bridge address (or node if not bridged) 
  171. for
  172.         network:node address.
  173.   Pre: dest_network - network number of workstation.
  174.          dest_node    - network node of workstation.
  175.                 dest_socket  - network socket of workstation.
  176.         Post: bridge_address is routing information used by 
  177. IPXSendPacket.
  178.          Return 00 - Success.
  179.                        FA - No path to destination. }
  180. function IPXGetLocalTarget( var dest_network   : NetworkNumber;
  181.                             var dest_node      : NetworkNode;
  182.                                 dest_socket    : word;
  183.                             var bridge_address : NetworkNode ) : byte;
  184.  
  185. { IPXGetIntervalMarker - Return time marker measured in 18.2/sec ticks.
  186.  Pre: None.
  187.         Post: Return time marker. }
  188. function IPXGetIntervalMarker : word;
  189.  
  190. { IPXSend -  Send a packet to network:node:socket using send_ecb and
  191.              send_header. send_ecb/send_header should be defined outside of
  192.              IPXSend as both may be in use by ipx after IPXSend completes,
  193.              releasing any local variables.
  194.     Pre: dest_network - network number of destination.
  195.                 dest_node    - network node of destination.
  196.                 dest_socket  - socket of destination.
  197.                 packet_ptr   - pointer to send packet.
  198.   packet_len   - length of send packet
  199.   send_ecb     - ECB to use for sending.
  200.                 send_header  - IPXHEADER to use for sending.
  201.                 send_socket  - socket to use for sending.
  202.         Post:   If destination reachable, packet is sent. }
  203. procedure IPXSend(  var dest_network   : NetworkNumber;
  204.                     var dest_node      : NetworkNode;
  205.                         dest_socket    : word; { hi:lo }
  206.                         packet_ptr     : Pointer;
  207.                         packet_len     : integer;
  208.                     var send_ecb       : ECB;
  209.                     var send_header    : IPXHEADER;
  210.                      send_socket    : word );
  211.  
  212. { IPXReceive - Submit an ECB/header and storage buffer for a received
  213.          message.
  214.     Pre:    receive_ecb    - ECB allocated for recieving.
  215.   receive_header - IPXHEADER allocated for receiving.
  216.                 receive_socket - socket to receive on.
  217.  Post: message        - area allocated for received message
  218.             holds data.
  219.                 message_size   - size of message area in bytes.  
  220.   }
  221. procedure IPXReceive(  var receive_ecb    : ECB;
  222.                        var receive_header : IPXHEADER;
  223.                            receive_socket : word;
  224.                            message        : Pointer;
  225.                            message_size   : word );
  226. { IPXReceivedFrame - Returns TRUE if message frame received in ECB.
  227.     Pre:    receive_ecb    - ECB allocated for recieving.
  228.  Post: Returns TRUE if message frame received in ECB.  
  229. }
  230. function IPXReceivedFrame( receive_ecb : ECB ) : Boolean;
  231.  
  232.    
  233. {_________________________________________________________________________}
  234.  
  235. implementation
  236.    type
  237.      REQUESTBUFFER       = record
  238.                             dest_network_number   : NetWorkNumber;
  239.                             dest_network_node     : NetworkNode;
  240.                             dest_network_socket   : word;
  241.                            end;
  242.      REPLYBUFFER         = record
  243.                             node_address          : NetworkNode;
  244.                            end;
  245.    var IPXLocation : Pointer;              { Address of ipx }
  246.  
  247. { abort - Display message and halt.
  248.    Pre:  message is a string. }
  249. procedure abort( message : string );
  250. begin
  251.      writeln( message );
  252.      Halt(1);
  253. end;
  254.  
  255. {$F+}
  256. { Get1stConnectionNumber - Return first connection number for user name
  257.  Pre: username is valid Novell user name
  258.         Post: Returns first connection number username is logged on or
  259.          0 if not logged on. }
  260. function Get1stConnectionNumber( username : string ) : word;
  261. var
  262.   NovRegs          : Registers;
  263.   Request          : record
  264.                        len            : Word;
  265.                        buffer_type    : Byte;
  266.                        object_type    : Word;
  267.                        name           : string[47];
  268.                      end;
  269.   Reply            : record
  270.                        len                : Word;
  271.                        number_connections : byte;
  272.                        connection_num     : array[0..99] of byte;
  273.                      end;
  274. begin
  275.   with Request do begin
  276.     len  := 51;
  277.     buffer_type := $15;
  278.     object_type := $0100;
  279.     name := username;
  280.   end;
  281.  
  282.   Reply.len := 101;     { Maximum number of user connections }
  283.  
  284.   with NovRegs do begin
  285.     AH := $E3;
  286.     DS := Seg(Request);  {DS:SI points to request}
  287.     SI := Ofs(Request);
  288.     ES := Seg(Reply);    {ES:DI points to reply}
  289.     DI := Ofs(Reply);
  290.     MsDos(NovRegs);
  291.  
  292.     if (Al <> 0) or (Reply.number_connections = 0)
  293.        then Get1stConnectionNumber := 0
  294.        else Get1stConnectionNumber := Reply.connection_num[0];
  295.   end;
  296. end;
  297.  
  298. { GetInternetAddress - Get the network:node address for a connection.
  299.  Pre: connection_number is valid for a logged on user.
  300.         Post: network_number is valid number of network.
  301.          physical_node is valid station node.             
  302.  }
  303. function GetInternetAddress(    connection_number : byte;
  304.                             var network_number : NetworkNumber; {hi:lo}
  305.                             var physical_node : NetworkNode ) : integer;
  306. var
  307.   NovRegs          : Registers;
  308.   Request          : record
  309.                        len               : word;
  310.                        buffer_type       : byte;
  311.                        connection_number : byte;
  312.                      end;
  313.   Reply            : record
  314.                        len            : word;
  315.                        network_number : NetworkNumber;
  316.                        physical_node  : NetworkNode;
  317.                        server_socket  : word;
  318.                      end;
  319. begin
  320.   with Request do begin
  321.     len  := 2;
  322.     buffer_type := $13;
  323.   end;
  324.   Request.connection_number := connection_number;
  325.   Reply.len := 12;
  326.   with NovRegs do begin
  327.     AH := $E3;
  328.     DS := Seg(Request);  {DS:SI points to request}
  329.     SI := Ofs(Request);
  330.     ES := Seg(Reply);    {ES:DI points to reply}
  331.     DI := Ofs(Reply);
  332.     MsDos(NovRegs);
  333.     Ah := 0;
  334.     GetInternetAddress := Ax;
  335.   end;
  336.   network_number := Reply.network_number;
  337.   physical_node := Reply.physical_node;
  338. end;
  339.  
  340. { IPXSPXNotLoaded - Executed when ipxspx called but not loaded.
  341.  Pre: IPX not loaded.
  342.         Post: Execution aborted. }
  343. procedure IPXSPXNotLoaded(var NovRegs : Registers);
  344. begin
  345.      abort('IPX not loaded');
  346. end;
  347.  
  348.  { ZeroEcb - store zeros in all ecb fields.
  349.  Pre: e is an ECB.
  350.         Post: e is fully zeroed. }
  351. procedure ZeroEcb( var e : ECB );
  352. var i : byte;
  353. begin
  354.      with e do begin
  355.           link_address := Ptr(0,0);
  356.           event_service_routine := Ptr(0,0);
  357.           in_use := 0;
  358.           completion_code := 0;
  359.           socket_number   := 0;
  360.           for i := 0 to 3 do
  361.               ipx_workspace[i] := 0;
  362.           for i := 0 to 11 do
  363.               driver_workspace[i] := 0;
  364.           for i := 0 to 5 do
  365.               immediate_address[i] := 0;
  366.           fragment_count := 0;
  367.           for i := 0 to 1 do begin
  368.               fragment[i].address := Ptr(0,0);
  369.               fragment[i].length  := 0;
  370.           end;
  371.      end;
  372. end;
  373.  
  374. { ZeroHeader - Store zeros in all header fields.
  375.  Pre: h is an IPXHEADER.
  376.         Post: h is fulled zeroed. }
  377. procedure ZeroHeader( var h : IPXHEADER );
  378. var i : byte;
  379. begin
  380.    with h do begin
  381.      checksum              := 0;
  382.      length                := 0;
  383.      transport_control     := 0;
  384.      packet_type           := 0;
  385.      for i := 0 to 3 do
  386.          dest_network_number[i] := 0;
  387.      for i := 0 to 5 do
  388.          dest_network_node[i] := 0;
  389.      dest_network_socket   := 0;
  390.      for i := 0 to 3 do
  391.          source_network_number[i] := 0;
  392.      for i := 0 to 5 do
  393.          source_network_node[i] := 0;
  394.      source_network_socket := 0;
  395.   end;
  396. end;
  397.  
  398.  { IPXInstalled - Determine if IPX is installed on workstation.
  399.  Pre: Either IPX is or is not installed.
  400.         Post:   If IPX installed initialize global IPXLocation to IPX 
  401. entry
  402.          point and return TRUE.
  403.                 Otherwise initialize global IPXLocation to 
  404. IPXSPXNotLoaded
  405.                 entry point and return FALSE.  }
  406. function IPXInstalled : Boolean;
  407. var NovRegs          : IPX_REGS;
  408. begin
  409.   with NovRegs do begin
  410.     AX := $7A00;             {func 7Ah of int 2Fh is used to detect IPX}
  411.     Intr($2F,NovRegs);
  412.     if AL = $FF then begin   {if AL is FFh then IPX is loaded and 
  413. available}
  414.       IPXInstalled := TRUE;
  415.       IPXLocation := Ptr(ES,DI); {pointer to IPX entry point in ES:DI}
  416.     end
  417.     else begin
  418.       IPXInstalled := FALSE; {no IPX installed}
  419.       IPXLocation := @IPXSPXNotLoaded;
  420.     end;
  421.   end;
  422. end;
  423.  
  424. { IPXSPX - Call ipxspx at address in IPXLocation.
  425.  Pre: IPXInstalled has been called.
  426.          IPX is installed and NovRegs assigned IPX or SPX 
  427. function
  428.          and parameter values. Not checking is done.
  429.         Post:  IPX or SPX function is called.
  430.          NovRegs assigned by call. }
  431. procedure IPXSPX(var NovRegs:Registers);
  432. var   Ax_, Bx_, Dx_, Di_, Si_, Es_ : word;
  433. begin
  434.      with NovRegs do begin  { Assign simple variables record field 
  435. values }
  436.           Ax_ := Ax;
  437.           Bx_ := Bx;
  438.           Dx_ := Dx;
  439.           Di_ := Di;
  440.           Si_ := Si;
  441.           Es_ := Es;
  442.      end;
  443.  
  444.      asm                            { Assembler instructions. }
  445.         mov   Ax, Ax_               { Initialize CPU registers.}
  446.         mov   Bx, Bx_
  447.         mov   Dx, Dx_
  448.         mov   Di, Di_
  449.         mov   Si, Si_
  450.         mov   Es, Es_
  451.  
  452.         push  Bp
  453.         call  dword ptr IPXLocation { Call IPX via address at 
  454. IPXLocation. }
  455.         pop   Bp
  456.         mov   Ax_, Ax
  457.         mov   Dx_, Dx
  458.      end;
  459.  
  460.      NovRegs.Ax := Ax_;             { Return register values to caller }
  461.      NovRegs.Dx := Dx_;
  462. end;
  463.  
  464. { IPXRelinquishControl - Give ipx momentary control of CPU.
  465.  Pre: IPX loaded.
  466.         Post: IPX execution done. }
  467. procedure IPXRelinquishControl;
  468. var NovRegs : IPX_REGS;
  469. begin
  470.      with NovRegs do begin
  471.           Bx := $0a;
  472.           IPXSPX(NovRegs);
  473.      end
  474. end;
  475.  
  476. { IPXCancelEvent - Cancels pending event associated with ECB.
  477.             Pre:  e is valid ECB.
  478.                    Post: 00 - Success.
  479.                      F9 - ECB cannot be canceled.
  480.                          FF - ECB not in use. }
  481. function IPXCancelEvent( var e : ECB ) : byte;
  482. var NovRegs : IPX_REGS;
  483. begin
  484.      with NovRegs do begin
  485.           Bx := $06;
  486.           ES := Seg(e);    {ES:SI points to ecb}
  487.           SI := Ofs(e);
  488.           IPXSPX(NovRegs);
  489.           IPXCancelEvent := AL;
  490.      end
  491. end;
  492.  
  493. { IPXDisconnectFromTarget - Notify listening node that communications 
  494. woth
  495.        specified socket are being terminated.
  496.  Pre: number:node:socket are valid.
  497.         Post: Node notified.   }
  498. procedure IPXDisconnectFromTarget( network_number : NetWorkNumber;
  499.                                    network_node   : NetWorkNode;
  500.                                    network_socket : word );
  501. var NovRegs : IPX_REGS;
  502.     request_buffer : REQUESTBUFFER;
  503. begin
  504.      with request_buffer do begin
  505.           dest_network_number := network_number;
  506.           dest_network_node   := network_node;
  507.    dest_network_socket := network_socket;
  508.      end;
  509.  
  510.      with NovRegs do begin
  511.           Bx := $0B;
  512.           ES := Seg(request_buffer);    {ES:SI points to ecb}
  513.           SI := Ofs(request_buffer);
  514.           IPXSPX(NovRegs);
  515.      end
  516. end;
  517.  
  518. { IPXScheduleEvent - Schedule processing of ECB after timer ticks.
  519.  Pre: ticks is number of 18.2 per second ticks.
  520.                 e is a valid ECB at the time processing occurs.
  521.         Post: e is processed after timer ticks. }
  522. procedure IPXScheduleEvent( ticks : word; var e : ECB );
  523. var NovRegs : IPX_REGS;
  524. begin
  525.      with NovRegs do begin
  526.           Bx := $05;
  527.           Ax := ticks;
  528.           ES := Seg(e);
  529.           SI := Ofs(e);
  530.           IPXSPX(NovRegs);
  531.      end;
  532. end;
  533.  
  534. { IPXOpenSocket - Open an application socket.
  535.  Pre: socket to use (BBA-7FFF). All assumed short-lived.
  536.         Post: 00 - Success.
  537.          FE - Socket table full.
  538.                 FF - Socket already open.  }
  539. function IPXOpenSocket( socket : word ) : byte;
  540. var NovRegs : IPX_REGS;
  541. begin
  542.      with NovRegs do begin
  543.           Dx := socket;
  544.           Bx := 0;
  545.           Al := 0;
  546.           IPXSPX(NovRegs);
  547.           Ah := 0;
  548.           IPXOpenSocket := Ax;
  549.      end
  550. end;
  551.  
  552. { IPXCloseSocket - Close socket. No harm if already closed.
  553.  Pre: socket to close.
  554.         Post: socket is closed. }
  555. procedure IPXCloseSocket( socket : word );
  556. var NovRegs : IPX_REGS;
  557. begin
  558.      with NovRegs do begin
  559.           Dx := socket;
  560.           Bx := $0001;
  561.           IPXSPX(NovRegs);
  562.      end
  563. end;
  564.  
  565.  { IPXListenForPacket - Submit an ECB for use when packet received. Must
  566.                        have ECB available when packet received by IPX.
  567.  Pre: e storage is available when ECB processed by IPX.
  568.           e.socket_number opened.
  569.                 e.event_svc-routine valid routine or NULL.
  570.                 e.fragment_count normally 2.
  571.                 e.fragment[0].address to IPX Header buffer.
  572.                 e.fragment[0].length = 30.
  573.                 e.fragment[1].address to data area <=546 bytes long.
  574.                 e.fragment[1].length = length of data area.
  575.         Post: If socket opened, e is added to pool and return TRUE.
  576.          Otherwise return FALSE.    }
  577. function IPXListenForPacket( var e : ECB ) : Boolean;
  578. var NovRegs : IPX_REGS;
  579. begin
  580.      with NovRegs do begin
  581.           BX := $0004;
  582.           ES := Seg(e);    {ES:SI points to ecb}
  583.           SI := Ofs(e);
  584.           IPXSPX(NovRegs);
  585.           IPXListenForPacket := Al = 00;
  586.      end
  587. end;
  588.  
  589. { IPXSendPacket - Send packet using given ECB.
  590.  Pre: e storage is available when ECB processed by IPX.
  591.          e.socket_number opened.
  592.                 e.event_svc-routine valid routine or NULL.
  593.                 e.immediate_address is address of destination 
  594. workstation.
  595.                 e.fragment_count normally 2.
  596.                 e.fragment[0].address to IPX Header buffer.
  597.                 e.fragment[0].length = 30.
  598.                 e.fragment[1].address to data area <=546 bytes long.
  599.                 e.fragment[1].length = length of data area.
  600.         Post: e.completion_code of: 00 - Message sent.
  601.             FC - Event canceled.
  602.                                         FD - Bad packet.   }
  603. procedure IPXSendPacket( var e: ECB );
  604. var NovRegs : IPX_REGS;
  605. begin
  606.      with NovRegs do begin
  607.           ES := Seg(e);    {ES:SI points to ecb}
  608.           SI := Ofs(e);
  609.           BX := $0003;
  610.           IPXSPX(NovRegs);
  611.      end
  612. end;
  613.  
  614.  { IPXGetLocalTarget - Get the bridge address (or node if not bridged) 
  615. for
  616.         network:node address.
  617.   Pre: dest_network - network number of workstation.
  618.          dest_node    - network node of workstation.
  619.                 dest_socket  - network socket of workstation.
  620.         Post: bridge_address is routing information used by 
  621. IPXSendPacket.
  622.          Return 00 - Success.
  623.                        FA - No path to destination. }
  624. function IPXGetLocalTarget( var dest_network   : NetworkNumber;
  625.                             var dest_node      : NetworkNode;
  626.                                 dest_socket    : word;
  627.                             var bridge_address : NetworkNode ) : byte;
  628. var
  629.   NovRegs          : Registers;
  630.   Request          : record
  631.                        network_number    : NetworkNumber;
  632.                        physical_node     : NetworkNode;
  633.                        socket            : word;
  634.                      end;
  635.   Reply            : record
  636.                        local_target      : NetworkNode;
  637.                      end;
  638. begin
  639.      with Request do begin
  640.           network_number := dest_network;
  641.           physical_node := dest_node;
  642.           socket := dest_socket;
  643.      end;
  644.      with NovRegs do begin
  645.           Es := Seg(Request);
  646.           Si := Ofs(Request);
  647.           Di := Ofs(Reply);
  648.           Bx := $0002;
  649.           IPXSPX(NovRegs);
  650.           Ah := 0;
  651.           IPXGetLocalTarget := Ax;
  652.           bridge_address := Reply.local_target;
  653.      end
  654. end;
  655.  
  656. { IPXGetIntervalMarker - Return time marker measured in 18.2/sec ticks.
  657.  Pre: None.
  658.         Post: Return time marker. }
  659. function IPXGetIntervalMarker : word;
  660. var
  661.   NovRegs          : Registers;
  662. begin
  663.  
  664.      with NovRegs do begin
  665.           Bx := $0008;
  666.           IPXSPX(NovRegs);
  667.           IPXGetIntervalMarker := Ax;
  668.      end
  669. end;
  670.  
  671.  { IPXSend - Send a packet to network:node:socket using send_ecb and
  672.              send_header. send_ecb/send_header should be defined outside 
  673. of
  674.              IPXSend as both may be in use by ipx after IPXSend 
  675. completes,
  676.              releasing any local variables.
  677.     Pre: dest_network - network number of destination.
  678.                 dest_node    - network node of destination.
  679.                 dest_socket  - socket of destination.
  680.                 packet_ptr   - pointer to send packet.
  681.   packet_len   - length of send packet
  682.   send_ecb     - ECB to use for sending.
  683.                 send_header  - IPXHEADER to use for sending.
  684.                 send_socket  - socket to use for sending.
  685.         Post:   If destination reachable, packet is sent. }
  686. procedure IPXSend(  var dest_network   : NetworkNumber;
  687.                     var dest_node      : NetworkNode;
  688.                         dest_socket    : word; { hi:lo }
  689.                         packet_ptr     : Pointer;
  690.                         packet_len     : integer;
  691.                     var send_ecb       : ECB;
  692.                     var send_header    : IPXHEADER;
  693.                      send_socket    : word );
  694. begin
  695.      ZeroEcb(send_ecb);
  696.      ZeroHeader(send_header);
  697.      send_ecb.socket_number := send_socket;  { Socket used for sending }
  698.      if IPXGetLocalTarget( dest_network,
  699.            dest_node,
  700.                            dest_socket,
  701.                            send_ecb.immediate_address ) = 0
  702.         then begin
  703.              with send_ecb do begin
  704.                   fragment_count := 2;
  705.                   fragment[0].address := @send_header;
  706.                   fragment[0].length  := sizeof(IPXHEADER);
  707.                   fragment[1].address := packet_ptr;
  708.                   fragment[1].length  := packet_len;
  709.              end;
  710.              with send_header do begin
  711.                   packet_type         := 4;
  712.                   dest_network_number := dest_network;
  713.                   dest_network_node   := dest_node;
  714.                   dest_network_socket := dest_socket;
  715.              end;
  716.              IPXSendPacket( send_ecb );
  717.         end;
  718. end;
  719.  
  720.  { IPXReceive - Submit an ECB/header and storage buffer for a received
  721.          message.
  722.     Pre:    receive_ecb    - ECB allocated for recieving.
  723.   receive_header - IPXHEADER allocated for receiving.
  724.                 receive_socket - socket to receive on.
  725.  Post: message        - area allocated for received message
  726.             holds data.
  727.                 message_size   - size of message area in bytes.  
  728.   }
  729. procedure IPXReceive(  var receive_ecb    : ECB;
  730.                        var receive_header : IPXHEADER;
  731.                            receive_socket : word;
  732.                            message        : Pointer;
  733.                            message_size   : word );
  734. begin
  735.    ZeroEcb(receive_ecb);
  736.    ZeroHeader(receive_header);
  737.    with receive_ecb do begin
  738.         socket_number := receive_socket; { Socket used for receiving }
  739.         fragment_count := 2;
  740.         fragment[0].address := @receive_header;
  741.         fragment[0].length  := sizeof(IPXHEADER);
  742.         fragment[1].address := message;
  743.         fragment[1].length  := message_size;
  744.    end;
  745.     if not IPXListenForPacket( receive_ecb ) then
  746.      abort('IPX Error - Failure initializing.');
  747.    IPXRelinquishControl;              { Give ipx opportunity to process 
  748. }
  749. end;
  750.  
  751. { IPXReceivedFrame - Returns TRUE if message frame received in ECB.
  752.     Pre:    receive_ecb    - ECB allocated for recieving.
  753.  Post: Returns TRUE if message frame received in ECB.  
  754. }
  755. function IPXReceivedFrame( receive_ecb : ECB ) : Boolean;
  756. begin
  757.  IPXReceivedFrame := (receive_ecb.completion_code = 0) and
  758.                             (receive_ecb.in_use = 0);
  759.  
  760. end;
  761.  
  762. begin
  763. end.
  764.